package com.freecloud.bittorrent.demo.po;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.freecloud.bitorrent.common.util.bencode.BencodingUtils;
import com.freecloud.bittorrent.demo.constant.DhtConstant;
import io.netty.buffer.Unpooled;
import io.netty.channel.socket.DatagramPacket;
import lombok.*;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: maomao
 * @Date: 2021/11/24 4:45 下午
 */
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class KRPC {

    /**
     * 事务ID，用t表示
     */
    private String transactionId;
    /**
     * 本机节点ID
     */
    private byte[] selfNodeId;

    /**
     * 用y表示
     * <p>
     * q:表示查询
     * r:响应
     * e:错误
     * v:版本字符串
     */
    private String messageType;

    /**
     * messageType对应表示的命令，可以从q中获取具体命令
     * <p>
     * 命令字段，有4个
     * ping、find_node、get_peers、announce_peer
     */
    private String command;

    /**
     * 其他参数
     */
    private Map<String, Object> arg;

    /**
     * 远程地址
     */
    private InetSocketAddress remoteAddress;

    /**
     * 生成KRPC协议数据
     *
     * @return
     */
    public DatagramPacket getDatagramPacket() {
        Map<String, Object> msgMap = new HashMap<>();
        msgMap.put("t", command.getBytes());
        msgMap.put("y", messageType);
        if (CollUtil.isEmpty(arg)) {
            this.arg = new HashMap<>();
        }
        if (!arg.containsKey("id")) {
            arg.put("id", DhtConstant.SELF_NODE_ID);
        }
        if ("q".equals(messageType)) {
            msgMap.put("q", command.getBytes());
            msgMap.put("a", arg);
        } else {
            msgMap.put("r", arg);
        }
        log.debug("msgMap : {}", JSONUtil.toJsonStr(msgMap));
        byte[] buff = BencodingUtils.encode(msgMap);
        return new DatagramPacket(Unpooled.copiedBuffer(buff), remoteAddress);
    }
}
